<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta name="theme-color" content="#222"><meta name="generator" content="Hexo 6.3.0">

  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">



<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css" integrity="sha256-CTSx/A06dm1B063156EVh15m6Y67pAjZZaQc89LLSrU=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.1.1/animate.min.css" integrity="sha256-PR7ttpcvz8qrF57fur/yAx1qXMFJeJFiA6pSzWi0OIE=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fancyapps-ui/5.0.24/fancybox/fancybox.css" integrity="sha256-vQkngPS8jiHHH0I6ABTZroZk8NPZ7b+MUReOFE9UsXQ=" crossorigin="anonymous">

<script class="next-config" data-name="main" type="application/json">{"hostname":"rjyblog.gitee.io","root":"/","images":"/images","scheme":"Pisces","darkmode":false,"version":"8.18.2","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12},"copycode":{"enable":true,"style":null},"fold":{"enable":false,"height":500},"bookmark":{"enable":false,"color":"#222","save":"auto"},"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"stickytabs":false,"motion":{"enable":true,"async":false,"transition":{"menu_item":"fadeInDown","post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"prism":false,"i18n":{"placeholder":"搜索...","empty":"没有找到任何搜索结果：${query}","hits_time":"找到 ${hits} 个搜索结果（用时 ${time} 毫秒）","hits":"找到 ${hits} 个搜索结果"},"path":"/search.xml","localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false}}</script><script src="/js/config.js"></script>

    <meta name="description" content="Bitmap内存分配 Android 2.3.3 (API level 10)以及更早的Android版本中，Bitmap的像素数据保存在native内存中，像素数据内存的回收则在finalize()中进行回收，存在很大的不确定性，很容易导致OOM的发生； 从Android 3.0 (API level 11) 到Android 7.1 (API level 25)，像素数据存放在Java Hea">
<meta property="og:type" content="article">
<meta property="og:title" content="Bitmap内存分配以及回收">
<meta property="og:url" content="https://rjyblog.gitee.io/posts/68833f9e.html">
<meta property="og:site_name" content="任建勇的博客">
<meta property="og:description" content="Bitmap内存分配 Android 2.3.3 (API level 10)以及更早的Android版本中，Bitmap的像素数据保存在native内存中，像素数据内存的回收则在finalize()中进行回收，存在很大的不确定性，很容易导致OOM的发生； 从Android 3.0 (API level 11) 到Android 7.1 (API level 25)，像素数据存放在Java Hea">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2023-09-22T02:36:32.000Z">
<meta property="article:modified_time" content="2023-10-18T03:10:27.691Z">
<meta property="article:author" content="Jason">
<meta property="article:tag" content="Android">
<meta property="article:tag" content="Bitmap">
<meta name="twitter:card" content="summary">


<link rel="canonical" href="https://rjyblog.gitee.io/posts/68833f9e.html">



<script class="next-config" data-name="page" type="application/json">{"sidebar":"","isHome":false,"isPost":true,"lang":"zh-CN","comments":true,"permalink":"https://rjyblog.gitee.io/posts/68833f9e.html","path":"posts/68833f9e.html","title":"Bitmap内存分配以及回收"}</script>

<script class="next-config" data-name="calendar" type="application/json">""</script>
<title>Bitmap内存分配以及回收 | 任建勇的博客</title>
  








  <noscript>
    <link rel="stylesheet" href="/css/noscript.css">
  </noscript>
</head>

<body itemscope itemtype="http://schema.org/WebPage" class="use-motion">
  <div class="headband"></div>

  <main class="main">
    <div class="column">
      <header class="header" itemscope itemtype="http://schema.org/WPHeader"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏" role="button">
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <i class="logo-line"></i>
      <p class="site-title">任建勇的博客</p>
      <i class="logo-line"></i>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger" aria-label="搜索" role="button">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>



<nav class="site-nav">
  <ul class="main-menu menu"><li class="menu-item menu-item-home"><a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a></li><li class="menu-item menu-item-tags"><a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a></li><li class="menu-item menu-item-categories"><a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a></li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup"><div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off" maxlength="80"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close" role="button">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div class="search-result-container no-result">
  <div class="search-result-icon">
    <i class="fa fa-spinner fa-pulse fa-5x"></i>
  </div>
</div>

    </div>
  </div>

</header>
        
  
  <aside class="sidebar">

    <div class="sidebar-inner sidebar-nav-active sidebar-toc-active">
      <ul class="sidebar-nav">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <div class="sidebar-panel-container">
        <!--noindex-->
        <div class="post-toc-wrap sidebar-panel">
            <div class="post-toc animated"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#Bitmap%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D"><span class="nav-text">Bitmap内存分配</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#Android-12%E4%BD%8D%E5%9B%BE%E8%A7%A3%E7%A0%81%EF%BC%8C%E4%BD%BF%E7%94%A8native%E5%86%85%E5%AD%98"><span class="nav-text">Android 12位图解码，使用native内存</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E9%BB%98%E8%AE%A4pixel%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D"><span class="nav-text">默认pixel内存分配</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%AF%94%E4%BE%8B%E7%BC%A9%E6%94%BE%E6%88%96%E7%A1%AC%E4%BB%B6%E4%BD%8D%E5%9B%BE%E5%9C%BA%E6%99%AF%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D"><span class="nav-text">比例缩放或硬件位图场景内存分配</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Android-7%E4%BD%BF%E7%94%A8Java%E5%86%85%E5%AD%98"><span class="nav-text">Android 7使用Java内存</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Android4-4%E4%BD%BF%E7%94%A8Java%E5%86%85%E5%AD%98%EF%BC%8C%E6%94%AF%E6%8C%81%E5%85%B1%E4%BA%AB%E5%86%85%E5%AD%98"><span class="nav-text">Android4.4使用Java内存，支持共享内存</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Bitmap%E5%86%85%E5%AD%98%E5%9B%9E%E6%94%B6%E6%9C%BA%E5%88%B6"><span class="nav-text">Bitmap内存回收机制</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#NativeAllocationRegistry%E5%86%85%E5%AD%98%E5%9B%9E%E6%94%B6%E5%8E%9F%E7%90%86"><span class="nav-text">NativeAllocationRegistry内存回收原理</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Cleaner%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90"><span class="nav-text">Cleaner源码分析</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%8F%82%E8%80%83%E6%96%87%E7%AB%A0"><span class="nav-text">参考文章</span></a></li></ol></div>
        </div>
        <!--/noindex-->

        <div class="site-overview-wrap sidebar-panel">
          <div class="site-author animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="Jason"
      src="/images/avatar.png">
  <p class="site-author-name" itemprop="name">Jason</p>
  <div class="site-description" itemprop="description"></div>
</div>
<div class="site-state-wrap animated">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
        <a href="/archives/">
          <span class="site-state-item-count">66</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
          <a href="/categories/">
        <span class="site-state-item-count">13</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
          <a href="/tags/">
        <span class="site-state-item-count">23</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>

        </div>
      </div>
    </div>

    
  </aside>


    </div>

    <div class="main-inner post posts-expand">


  


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://rjyblog.gitee.io/posts/68833f9e.html">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.png">
      <meta itemprop="name" content="Jason">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="任建勇的博客">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="post" itemscope itemtype="http://schema.org/CreativeWork">
      <meta itemprop="name" content="Bitmap内存分配以及回收 | 任建勇的博客">
      <meta itemprop="description" content="">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          Bitmap内存分配以及回收
        </h1>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2023-09-22 10:36:32" itemprop="dateCreated datePublished" datetime="2023-09-22T10:36:32+08:00">2023-09-22</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar-check"></i>
      </span>
      <span class="post-meta-item-text">更新于</span>
      <time title="修改时间：2023-10-18 11:10:27" itemprop="dateModified" datetime="2023-10-18T11:10:27+08:00">2023-10-18</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/Android/" itemprop="url" rel="index"><span itemprop="name">Android</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody"><h2 id="Bitmap内存分配"><a href="#Bitmap内存分配" class="headerlink" title="Bitmap内存分配"></a>Bitmap内存分配</h2><ul>
<li>Android 2.3.3 (API level 10)以及更早的Android版本中，Bitmap的像素数据保存在native内存中，像素数据内存的回收则在finalize()中进行回收，存在很大的不确定性，很容易导致OOM的发生；</li>
<li>从Android 3.0 (API level 11) 到Android 7.1 (API level 25)，像素数据存放在Java Heap中，跟Bitmap对象一起回收。但由于图片是内存消耗大户，所以也很容易导致OOM，以及频繁的GC导致内存抖动问题。</li>
<li>在Android 8.0 (API level 26)以及更高的版本中，像素数据保存在native heap中。通过一个辅助类<code>NativeAllocationRegistry</code>来实现native内存的回收。</li>
</ul>
<p>在android.graphics.BitmapFactory类中有一系列函数可以解码生成Bitmap：</p>
<ul>
<li>Bitmap decodeByteArray(byte[] data, int offset, int length)</li>
<li>Bitmap decodeByteArray(byte[] data, int offset, int length, Options opts)</li>
<li>Bitmap decodeFile(String pathName)</li>
<li>Bitmap decodeFile(String pathName, Options opts)</li>
<li>…… 等等</li>
</ul>
<p>这些方法都会调用到jni层<code>frameworks\base\libs\hwui\jni\BitmapFactory.cpp</code>,最终都会走到<code>doDecode</code>方法：</p>
<h3 id="Android-12位图解码，使用native内存"><a href="#Android-12位图解码，使用native内存" class="headerlink" title="Android 12位图解码，使用native内存"></a>Android 12位图解码，使用native内存</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//frameworks\base\libs\hwui\jni\BitmapFactory.cpp</span></span><br><span class="line"><span class="function"><span class="type">static</span> jobject <span class="title">doDecode</span><span class="params">(JNIEnv* env, std::unique_ptr&lt;SkStreamRewindable&gt; stream,</span></span></span><br><span class="line"><span class="params"><span class="function">                        jobject padding, jobject options, jlong inBitmapHandle,</span></span></span><br><span class="line"><span class="params"><span class="function">                        jlong colorSpaceHandle)</span> </span>&#123;</span><br><span class="line">    ...... <span class="comment">//代码省略</span></span><br><span class="line">    <span class="comment">// Scale is necessary due to density differences.</span></span><br><span class="line">    <span class="keyword">if</span> (scale != <span class="number">1.0f</span>) &#123;</span><br><span class="line">        willScale = <span class="literal">true</span>;</span><br><span class="line">        scaledWidth = <span class="built_in">static_cast</span>&lt;<span class="type">int</span>&gt;(scaledWidth * scale + <span class="number">0.5f</span>);</span><br><span class="line">        scaledHeight = <span class="built_in">static_cast</span>&lt;<span class="type">int</span>&gt;(scaledHeight * scale + <span class="number">0.5f</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    android::Bitmap* reuseBitmap = <span class="literal">nullptr</span>;</span><br><span class="line">    <span class="type">unsigned</span> <span class="type">int</span> existingBufferSize = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">if</span> (javaBitmap != <span class="literal">nullptr</span>) &#123;</span><br><span class="line">        reuseBitmap = &amp;bitmap::<span class="built_in">toBitmap</span>(inBitmapHandle);</span><br><span class="line">        <span class="keyword">if</span> (reuseBitmap-&gt;<span class="built_in">isImmutable</span>()) &#123;</span><br><span class="line">            <span class="built_in">ALOGW</span>(<span class="string">&quot;Unable to reuse an immutable bitmap as an image decoder target.&quot;</span>);</span><br><span class="line">            javaBitmap = <span class="literal">nullptr</span>;</span><br><span class="line">            reuseBitmap = <span class="literal">nullptr</span>;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            existingBufferSize = reuseBitmap-&gt;<span class="built_in">getAllocationByteCount</span>();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    HeapAllocator defaultAllocator;</span><br><span class="line">    <span class="function">RecyclingPixelAllocator <span class="title">recyclingAllocator</span><span class="params">(reuseBitmap, existingBufferSize)</span></span>;</span><br><span class="line">    <span class="function">ScaleCheckingAllocator <span class="title">scaleCheckingAllocator</span><span class="params">(scale, existingBufferSize)</span></span>;</span><br><span class="line">    SkBitmap::HeapAllocator heapAllocator;</span><br><span class="line">    SkBitmap::Allocator* decodeAllocator;</span><br><span class="line">    <span class="keyword">if</span> (javaBitmap != <span class="literal">nullptr</span> &amp;&amp; willScale) &#123;</span><br><span class="line">        <span class="comment">// This will allocate pixels using a HeapAllocator, since there will be an extra</span></span><br><span class="line">        <span class="comment">// scaling step that copies these pixels into Java memory.  This allocator</span></span><br><span class="line">        <span class="comment">// also checks that the recycled javaBitmap is large enough.</span></span><br><span class="line">        decodeAllocator = &amp;scaleCheckingAllocator;</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (javaBitmap != <span class="literal">nullptr</span>) &#123;</span><br><span class="line">        decodeAllocator = &amp;recyclingAllocator;</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (willScale || isHardware) &#123;</span><br><span class="line">        <span class="comment">// This will allocate pixels using a HeapAllocator,</span></span><br><span class="line">        <span class="comment">// for scale case: there will be an extra scaling step.</span></span><br><span class="line">        <span class="comment">// for hardware case: there will be extra swizzling &amp; upload to gralloc step.</span></span><br><span class="line">        decodeAllocator = &amp;heapAllocator;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        decodeAllocator = &amp;defaultAllocator;</span><br><span class="line">    &#125;</span><br><span class="line">    ......</span><br><span class="line">    SkBitmap decodingBitmap; <span class="comment">//SkBitmap 是skia库中的类</span></span><br><span class="line">    <span class="comment">//decodingBitmap.tryAllocPixels的作用是分配piexel内存，最终调用的是</span></span><br><span class="line">    <span class="comment">//decodeAllocator-&gt;allocPixelRef(this);</span></span><br><span class="line">    <span class="keyword">if</span> (!decodingBitmap.<span class="built_in">setInfo</span>(bitmapInfo) ||</span><br><span class="line">            !decodingBitmap.<span class="built_in">tryAllocPixels</span>(decodeAllocator)) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nullptr</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Use SkAndroidCodec to perform the decode.</span></span><br><span class="line">    SkAndroidCodec::AndroidOptions codecOptions;</span><br><span class="line">    codecOptions.fZeroInitialized = decodeAllocator == &amp;defaultAllocator ?</span><br><span class="line">            SkCodec::kYes_ZeroInitialized : SkCodec::kNo_ZeroInitialized;</span><br><span class="line">    codecOptions.fSampleSize = sampleSize;</span><br><span class="line">    <span class="comment">//codec指的是SkAndroidCodec，是skia库中的类。下面这句代码就是真正的解码了</span></span><br><span class="line">    SkCodec::Result result = codec-&gt;<span class="built_in">getAndroidPixels</span>(decodeInfo, decodingBitmap.<span class="built_in">getPixels</span>(), </span><br><span class="line">            decodingBitmap.<span class="built_in">rowBytes</span>(), &amp;codecOptions);</span><br><span class="line">    </span><br><span class="line">    ......</span><br><span class="line">    <span class="comment">//按比例缩放位图</span></span><br><span class="line">    SkBitmap outputBitmap;</span><br><span class="line">    <span class="keyword">if</span> (willScale) &#123;</span><br><span class="line">        <span class="comment">// Set the allocator for the outputBitmap.</span></span><br><span class="line">        SkBitmap::Allocator* outputAllocator;</span><br><span class="line">        <span class="keyword">if</span> (javaBitmap != <span class="literal">nullptr</span>) &#123;</span><br><span class="line">            outputAllocator = &amp;recyclingAllocator;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            outputAllocator = &amp;defaultAllocator;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        SkColorType scaledColorType = decodingBitmap.<span class="built_in">colorType</span>();</span><br><span class="line">        <span class="comment">// <span class="doctag">FIXME:</span> If the alphaType is kUnpremul and the image has alpha, the</span></span><br><span class="line">        <span class="comment">// colors may not be correct, since Skia does not yet support drawing</span></span><br><span class="line">        <span class="comment">// to/from unpremultiplied bitmaps.</span></span><br><span class="line">        outputBitmap.<span class="built_in">setInfo</span>(</span><br><span class="line">                bitmapInfo.<span class="built_in">makeWH</span>(scaledWidth, scaledHeight).<span class="built_in">makeColorType</span>(scaledColorType));</span><br><span class="line">        <span class="keyword">if</span> (!outputBitmap.<span class="built_in">tryAllocPixels</span>(outputAllocator)) &#123;</span><br><span class="line">            <span class="comment">// This should only fail on OOM.  The recyclingAllocator should have</span></span><br><span class="line">            <span class="comment">// enough memory since we check this before decoding using the</span></span><br><span class="line">            <span class="comment">// scaleCheckingAllocator.</span></span><br><span class="line">            <span class="keyword">return</span> <span class="built_in">nullObjectReturn</span>(<span class="string">&quot;allocation failed for scaled bitmap&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        SkPaint paint;</span><br><span class="line">        <span class="comment">// kSrc_Mode instructs us to overwrite the uninitialized pixels in</span></span><br><span class="line">        <span class="comment">// outputBitmap.  Otherwise we would blend by default, which is not</span></span><br><span class="line">        <span class="comment">// what we want.</span></span><br><span class="line">        paint.<span class="built_in">setBlendMode</span>(SkBlendMode::kSrc);</span><br><span class="line"></span><br><span class="line">        <span class="function">SkCanvas <span class="title">canvas</span><span class="params">(outputBitmap, SkCanvas::ColorBehavior::kLegacy)</span></span>;</span><br><span class="line">        canvas.<span class="built_in">scale</span>(scaleX, scaleY);</span><br><span class="line">        decodingBitmap.<span class="built_in">setImmutable</span>(); <span class="comment">// so .asImage() doesn&#x27;t make a copy</span></span><br><span class="line">        canvas.<span class="built_in">drawImage</span>(decodingBitmap.<span class="built_in">asImage</span>(), <span class="number">0.0f</span>, <span class="number">0.0f</span>,</span><br><span class="line">                         <span class="built_in">SkSamplingOptions</span>(SkFilterMode::kLinear), &amp;paint);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        outputBitmap.<span class="built_in">swap</span>(decodingBitmap);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    ......</span><br><span class="line">    <span class="comment">//硬件位图</span></span><br><span class="line">    <span class="keyword">if</span> (isHardware) &#123;</span><br><span class="line">        <span class="comment">//GPU中分配位图内存。原outputBitmap是否需要释放呢？在哪释放？</span></span><br><span class="line">        sk_sp&lt;Bitmap&gt; hardwareBitmap = Bitmap::<span class="built_in">allocateHardwareBitmap</span>(outputBitmap);</span><br><span class="line">        <span class="keyword">if</span> (!hardwareBitmap.<span class="built_in">get</span>()) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="built_in">nullObjectReturn</span>(<span class="string">&quot;Failed to allocate a hardware bitmap&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//创建java层Bitmap，此处的hardwareBitmap.release()不是资源回收的意思，而是取出sk_sp中的Bitmap实例。</span></span><br><span class="line">        <span class="keyword">return</span> bitmap::<span class="built_in">createBitmap</span>(env, hardwareBitmap.<span class="built_in">release</span>(), bitmapCreateFlags,</span><br><span class="line">                ninePatchChunk, ninePatchInsets, <span class="number">-1</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// now create the java bitmap</span></span><br><span class="line">    <span class="keyword">return</span> bitmap::<span class="built_in">createBitmap</span>(env, defaultAllocator.<span class="built_in">getStorageObjAndReset</span>(),</span><br><span class="line">            bitmapCreateFlags, ninePatchChunk, ninePatchInsets, <span class="number">-1</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="默认pixel内存分配"><a href="#默认pixel内存分配" class="headerlink" title="默认pixel内存分配"></a>默认pixel内存分配</h4><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">bool</span> <span class="title">HeapAllocator::allocPixelRef</span><span class="params">(SkBitmap* bitmap)</span> </span>&#123;</span><br><span class="line">    mStorage = android::Bitmap::<span class="built_in">allocateHeapBitmap</span>(bitmap);</span><br><span class="line">    <span class="keyword">return</span> !!mStorage;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//frameworks\base\libs\hwui\hwui\Bitmap.cpp</span></span><br><span class="line"><span class="function">sk_sp&lt;Bitmap&gt; <span class="title">Bitmap::allocateHeapBitmap</span><span class="params">(SkBitmap* bitmap)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">allocateBitmap</span>(bitmap, &amp;Bitmap::allocateHeapBitmap);</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">static</span> sk_sp&lt;Bitmap&gt; <span class="title">allocateBitmap</span><span class="params">(SkBitmap* bitmap, AllocPixelRef alloc)</span> </span>&#123;</span><br><span class="line">    <span class="type">const</span> SkImageInfo&amp; info = bitmap-&gt;<span class="built_in">info</span>();</span><br><span class="line">    <span class="keyword">if</span> (info.<span class="built_in">colorType</span>() == kUnknown_SkColorType) &#123;</span><br><span class="line">        <span class="built_in">LOG_ALWAYS_FATAL</span>(<span class="string">&quot;unknown bitmap configuration&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nullptr</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="type">size_t</span> size;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// we must respect the rowBytes value already set on the bitmap instead of</span></span><br><span class="line">    <span class="comment">// attempting to compute our own.</span></span><br><span class="line">    <span class="type">const</span> <span class="type">size_t</span> rowBytes = bitmap-&gt;<span class="built_in">rowBytes</span>();</span><br><span class="line">    <span class="keyword">if</span> (!Bitmap::<span class="built_in">computeAllocationSize</span>(rowBytes, bitmap-&gt;<span class="built_in">height</span>(), &amp;size)) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nullptr</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">auto</span> wrapper = <span class="built_in">alloc</span>(size, info, rowBytes); <span class="comment">//使用入参的alloc函数分配内存</span></span><br><span class="line">    <span class="keyword">if</span> (wrapper) &#123;</span><br><span class="line">        wrapper-&gt;<span class="built_in">getSkBitmap</span>(bitmap);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> wrapper;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function">sk_sp&lt;Bitmap&gt; <span class="title">Bitmap::allocateHeapBitmap</span><span class="params">(<span class="type">size_t</span> size, <span class="type">const</span> SkImageInfo&amp; info, <span class="type">size_t</span> rowBytes)</span> </span>&#123;</span><br><span class="line">    <span class="type">void</span>* addr = <span class="built_in">calloc</span>(size, <span class="number">1</span>); <span class="comment">//调用Linux C库函数分配内存</span></span><br><span class="line">    <span class="keyword">if</span> (!addr) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nullptr</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">sk_sp</span>&lt;Bitmap&gt;(<span class="keyword">new</span> <span class="built_in">Bitmap</span>(addr, size, info, rowBytes)); <span class="comment">//返回最终的Bitmap对象</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="比例缩放或硬件位图场景内存分配"><a href="#比例缩放或硬件位图场景内存分配" class="headerlink" title="比例缩放或硬件位图场景内存分配"></a>比例缩放或硬件位图场景内存分配</h4><p>在需要将图片进行按比例缩放，或者使用硬件内存时，使用SkBitmap::HeapAllocator来分配内存。当解码位图时如果配置了<code>android.graphics.Bitmap.Config#HARDWARE</code>就会使用硬件位图。硬件位图是一种 Android O 添加的新的位图格式。硬件位图仅在显存 (graphic memory) 里存储像素数据，并对图片仅在屏幕上绘制的场景做了优化。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//external\skia\src\core\SkBitmap.cpp</span></span><br><span class="line"><span class="type">bool</span> SkBitmap::HeapAllocator::<span class="built_in">allocPixelRef</span>(SkBitmap* dst) &#123;</span><br><span class="line">    <span class="type">const</span> SkImageInfo&amp; info = dst-&gt;<span class="built_in">info</span>();</span><br><span class="line">    <span class="keyword">if</span> (kUnknown_SkColorType == info.<span class="built_in">colorType</span>()) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    sk_sp&lt;SkPixelRef&gt; pr = SkMallocPixelRef::<span class="built_in">MakeAllocate</span>(info, dst-&gt;<span class="built_in">rowBytes</span>());</span><br><span class="line">    <span class="keyword">if</span> (!pr) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    dst-&gt;<span class="built_in">setPixelRef</span>(std::<span class="built_in">move</span>(pr), <span class="number">0</span>, <span class="number">0</span>);</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//external\skia\src\core\SkMallocPixelRef.cpp</span></span><br><span class="line"><span class="function">sk_sp&lt;SkPixelRef&gt; <span class="title">SkMallocPixelRef::MakeAllocate</span><span class="params">(<span class="type">const</span> SkImageInfo&amp; info, <span class="type">size_t</span> rowBytes)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (rowBytes == <span class="number">0</span>) &#123;</span><br><span class="line">        rowBytes = info.<span class="built_in">minRowBytes</span>();</span><br><span class="line">        <span class="comment">// rowBytes can still be zero, if it overflowed (width * bytesPerPixel &gt; size_t)</span></span><br><span class="line">        <span class="comment">// or if colortype is unknown</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (!<span class="built_in">is_valid</span>(info) || !info.<span class="built_in">validRowBytes</span>(rowBytes)) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nullptr</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="type">size_t</span> size = info.<span class="built_in">computeByteSize</span>(rowBytes);</span><br><span class="line">    <span class="keyword">if</span> (SkImageInfo::<span class="built_in">ByteSizeOverflowed</span>(size)) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nullptr</span>;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="meta">#<span class="keyword">if</span> defined(SK_BUILD_FOR_FUZZER)</span></span><br><span class="line">    <span class="keyword">if</span> (size &gt; <span class="number">100000</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nullptr</span>;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line">    <span class="type">void</span>* addr = <span class="built_in">sk_calloc_canfail</span>(size);</span><br><span class="line">    <span class="keyword">if</span> (<span class="literal">nullptr</span> == addr) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nullptr</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">struct</span> <span class="title class_">PixelRef</span> <span class="keyword">final</span> : <span class="keyword">public</span> SkPixelRef &#123;</span><br><span class="line">        <span class="built_in">PixelRef</span>(<span class="type">int</span> w, <span class="type">int</span> h, <span class="type">void</span>* s, <span class="type">size_t</span> r) : <span class="built_in">SkPixelRef</span>(w, h, s, r) &#123;&#125;</span><br><span class="line">        ~<span class="built_in">PixelRef</span>() <span class="keyword">override</span> &#123; <span class="built_in">sk_free</span>(<span class="keyword">this</span>-&gt;<span class="built_in">pixels</span>()); &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">sk_sp</span>&lt;SkPixelRef&gt;(<span class="keyword">new</span> <span class="built_in">PixelRef</span>(info.<span class="built_in">width</span>(), info.<span class="built_in">height</span>(), addr, rowBytes));</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//external\skia\include\private\SkMalloc.h</span></span><br><span class="line"><span class="function"><span class="type">static</span> <span class="keyword">inline</span> <span class="type">void</span>* <span class="title">sk_calloc_canfail</span><span class="params">(<span class="type">size_t</span> size)</span> </span>&#123;</span><br><span class="line"><span class="meta">#<span class="keyword">if</span> defined(SK_BUILD_FOR_FUZZER)</span></span><br><span class="line">    <span class="comment">// To reduce the chance of OOM, pretend we can&#x27;t allocate more than 200kb.</span></span><br><span class="line">    <span class="keyword">if</span> (size &gt; <span class="number">200000</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nullptr</span>;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">sk_malloc_flags</span>(size, SK_MALLOC_ZERO_INITIALIZE);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//external\skia\src\ports\SkMemory_malloc.cpp</span></span><br><span class="line"><span class="function"><span class="type">void</span>* <span class="title">sk_malloc_flags</span><span class="params">(<span class="type">size_t</span> size, <span class="type">unsigned</span> flags)</span> </span>&#123;</span><br><span class="line">    <span class="type">void</span>* p;</span><br><span class="line">    <span class="keyword">if</span> (flags &amp; SK_MALLOC_ZERO_INITIALIZE) &#123;</span><br><span class="line">        p = <span class="built_in">calloc</span>(size, <span class="number">1</span>);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"><span class="meta">#<span class="keyword">if</span> defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) &amp;&amp; defined(__BIONIC__)</span></span><br><span class="line">        <span class="comment">/* <span class="doctag">TODO:</span> After b/169449588 is fixed, we will want to change this to restore</span></span><br><span class="line"><span class="comment">         *       original behavior instead of always disabling the flag.</span></span><br><span class="line"><span class="comment">         * <span class="doctag">TODO:</span> After b/158870657 is fixed and scudo is used globally, we can assert when an</span></span><br><span class="line"><span class="comment">         *       an error is returned.</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        <span class="comment">// malloc() generally doesn&#x27;t initialize its memory and that&#x27;s a huge security hole,</span></span><br><span class="line">        <span class="comment">// so Android has replaced its malloc() with one that zeros memory,</span></span><br><span class="line">        <span class="comment">// but that&#x27;s a huge performance hit for HWUI, so turn it back off again.</span></span><br><span class="line">        (<span class="type">void</span>)<span class="built_in">mallopt</span>(M_THREAD_DISABLE_MEM_INIT, <span class="number">1</span>);</span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line">        p = <span class="built_in">malloc</span>(size);</span><br><span class="line"><span class="meta">#<span class="keyword">if</span> defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) &amp;&amp; defined(__BIONIC__)</span></span><br><span class="line">        (<span class="type">void</span>)<span class="built_in">mallopt</span>(M_THREAD_DISABLE_MEM_INIT, <span class="number">0</span>);</span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (flags &amp; SK_MALLOC_THROW) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">throw_on_failure</span>(size, p);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> p;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="Android-7使用Java内存"><a href="#Android-7使用Java内存" class="headerlink" title="Android 7使用Java内存"></a>Android 7使用Java内存</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//frameworks\base\core\jni\android\graphics\BitmapFactory.cpp</span></span><br><span class="line"><span class="function"><span class="type">static</span> jobject <span class="title">doDecode</span><span class="params">(JNIEnv* env, SkStreamRewindable* stream, jobject padding, jobject options)</span> </span>&#123;</span><br><span class="line">    ...... <span class="comment">//代码省略</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">//JavaPixelAllocator就是从Java heap中分配内存，JavaPixelAllocator中通过</span></span><br><span class="line">    <span class="comment">//使用dalvik.system.VMRuntime.getRuntime().newNonMovableArray来申请内存</span></span><br><span class="line">    <span class="function">JavaPixelAllocator <span class="title">javaAllocator</span><span class="params">(env)</span></span>;</span><br><span class="line">    <span class="comment">//复用inBitmap</span></span><br><span class="line">    <span class="function">RecyclingPixelAllocator <span class="title">recyclingAllocator</span><span class="params">(reuseBitmap, existingBufferSize)</span></span>;</span><br><span class="line">    <span class="comment">//ScaleCheckingAllocator内部通过SkBitmap::HeapAllocator来申请native内存，但是</span></span><br><span class="line">    <span class="comment">//这个内存只是临时内存，在后面的scale操作时会最终申请java内存，native内存会被释放</span></span><br><span class="line">    <span class="function">ScaleCheckingAllocator <span class="title">scaleCheckingAllocator</span><span class="params">(scale, existingBufferSize)</span></span>;</span><br><span class="line">    <span class="comment">//SkBitmap::HeapAllocator是skia库提供的内存分派类，使用native内存</span></span><br><span class="line">    SkBitmap::HeapAllocator heapAllocator;</span><br><span class="line">    SkBitmap::Allocator* decodeAllocator;</span><br><span class="line">    <span class="keyword">if</span> (javaBitmap != <span class="literal">nullptr</span> &amp;&amp; willScale) &#123;</span><br><span class="line">        <span class="comment">// This will allocate pixels using a HeapAllocator, since there will be an extra</span></span><br><span class="line">        <span class="comment">// scaling step that copies these pixels into Java memory.  This allocator</span></span><br><span class="line">        <span class="comment">// also checks that the recycled javaBitmap is large enough.</span></span><br><span class="line">        decodeAllocator = &amp;scaleCheckingAllocator;</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (javaBitmap != <span class="literal">nullptr</span>) &#123;</span><br><span class="line">        decodeAllocator = &amp;recyclingAllocator;</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (willScale) &#123;</span><br><span class="line">        <span class="comment">// This will allocate pixels using a HeapAllocator, since there will be an extra</span></span><br><span class="line">        <span class="comment">// scaling step that copies these pixels into Java memory.</span></span><br><span class="line">        decodeAllocator = &amp;heapAllocator;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        decodeAllocator = &amp;javaAllocator;</span><br><span class="line">    &#125;</span><br><span class="line">    ......</span><br><span class="line">    SkBitmap outputBitmap;</span><br><span class="line">    <span class="keyword">if</span> (willScale) &#123;</span><br><span class="line">        <span class="comment">// This is weird so let me explain: we could use the scale parameter</span></span><br><span class="line">        <span class="comment">// directly, but for historical reasons this is how the corresponding</span></span><br><span class="line">        <span class="comment">// Dalvik code has always behaved. We simply recreate the behavior here.</span></span><br><span class="line">        <span class="comment">// The result is slightly different from simply using scale because of</span></span><br><span class="line">        <span class="comment">// the 0.5f rounding bias applied when computing the target image size</span></span><br><span class="line">        <span class="type">const</span> <span class="type">float</span> sx = scaledWidth / <span class="built_in">float</span>(decodingBitmap.<span class="built_in">width</span>());</span><br><span class="line">        <span class="type">const</span> <span class="type">float</span> sy = scaledHeight / <span class="built_in">float</span>(decodingBitmap.<span class="built_in">height</span>());</span><br><span class="line"></span><br><span class="line">        <span class="comment">// Set the allocator for the outputBitmap.</span></span><br><span class="line">        SkBitmap::Allocator* outputAllocator;</span><br><span class="line">        <span class="keyword">if</span> (javaBitmap != <span class="literal">nullptr</span>) &#123;</span><br><span class="line">            outputAllocator = &amp;recyclingAllocator; <span class="comment">//复用inBitmap</span></span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            outputAllocator = &amp;javaAllocator; <span class="comment">//使用Java内存</span></span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        SkColorType scaledColorType = <span class="built_in">colorTypeForScaledOutput</span>(decodingBitmap.<span class="built_in">colorType</span>());</span><br><span class="line">        <span class="comment">// <span class="doctag">FIXME:</span> If the alphaType is kUnpremul and the image has alpha, the</span></span><br><span class="line">        <span class="comment">// colors may not be correct, since Skia does not yet support drawing</span></span><br><span class="line">        <span class="comment">// to/from unpremultiplied bitmaps.</span></span><br><span class="line">        outputBitmap.<span class="built_in">setInfo</span>(SkImageInfo::<span class="built_in">Make</span>(scaledWidth, scaledHeight,</span><br><span class="line">                scaledColorType, decodingBitmap.<span class="built_in">alphaType</span>()));</span><br><span class="line">        <span class="keyword">if</span> (!outputBitmap.<span class="built_in">tryAllocPixels</span>(outputAllocator, <span class="literal">NULL</span>)) &#123;</span><br><span class="line">            <span class="comment">// This should only fail on OOM.  The recyclingAllocator should have</span></span><br><span class="line">            <span class="comment">// enough memory since we check this before decoding using the</span></span><br><span class="line">            <span class="comment">// scaleCheckingAllocator.</span></span><br><span class="line">            <span class="keyword">return</span> <span class="built_in">nullObjectReturn</span>(<span class="string">&quot;allocation failed for scaled bitmap&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        SkPaint paint;</span><br><span class="line">        <span class="comment">// kSrc_Mode instructs us to overwrite the unininitialized pixels in</span></span><br><span class="line">        <span class="comment">// outputBitmap.  Otherwise we would blend by default, which is not</span></span><br><span class="line">        <span class="comment">// what we want.</span></span><br><span class="line">        paint.<span class="built_in">setXfermodeMode</span>(SkXfermode::kSrc_Mode);</span><br><span class="line">        paint.<span class="built_in">setFilterQuality</span>(kLow_SkFilterQuality);</span><br><span class="line"></span><br><span class="line">        <span class="function">SkCanvas <span class="title">canvas</span><span class="params">(outputBitmap)</span></span>;</span><br><span class="line">        canvas.<span class="built_in">scale</span>(sx, sy);</span><br><span class="line">        canvas.<span class="built_in">drawBitmap</span>(decodingBitmap, <span class="number">0.0f</span>, <span class="number">0.0f</span>, &amp;paint);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        outputBitmap.<span class="built_in">swap</span>(decodingBitmap);</span><br><span class="line">    &#125;</span><br><span class="line">    ......</span><br></pre></td></tr></table></figure>

<h3 id="Android4-4使用Java内存，支持共享内存"><a href="#Android4-4使用Java内存，支持共享内存" class="headerlink" title="Android4.4使用Java内存，支持共享内存"></a>Android4.4使用Java内存，支持共享内存</h3><?xml version="1.0" encoding="us-ascii" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" height="526px" preserveAspectRatio="none" style="width:1114px;height:526px;background:#FFFFFF;" version="1.1" viewBox="0 0 1114 526" width="1114px" zoomAndPan="magnify"><defs/><g><!--class SkImageDecoder--><g id="elem_SkImageDecoder"><rect fill="#F1F1F1" height="48" id="SkImageDecoder" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="155" x="353.5" y="7"/><ellipse cx="368.5" cy="23" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M370.8438,18.6719 C369.9063,18.2344 369.3125,18.0938 368.4375,18.0938 C365.8125,18.0938 363.8125,20.1719 363.8125,22.8906 L363.8125,24.0156 C363.8125,26.5938 365.9219,28.4844 368.8125,28.4844 C370.0313,28.4844 371.1875,28.1875 371.9375,27.6406 C372.5156,27.2344 372.8438,26.7813 372.8438,26.3906 C372.8438,25.9375 372.4531,25.5469 371.9844,25.5469 C371.7656,25.5469 371.5625,25.625 371.375,25.8125 C370.9219,26.2969 370.9219,26.2969 370.7344,26.3906 C370.3125,26.6563 369.625,26.7813 368.8594,26.7813 C366.8125,26.7813 365.5156,25.6875 365.5156,23.9844 L365.5156,22.8906 C365.5156,21.1094 366.7656,19.7969 368.5,19.7969 C369.0781,19.7969 369.6875,19.9531 370.1563,20.2031 C370.6406,20.4844 370.8125,20.7031 370.9063,21.1094 C370.9688,21.5156 371,21.6406 371.1406,21.7656 C371.2813,21.9063 371.5156,22.0156 371.7344,22.0156 C372,22.0156 372.2656,21.875 372.4375,21.6563 C372.5469,21.5 372.5781,21.3125 372.5781,20.8906 L372.5781,19.4688 C372.5781,19.0313 372.5625,18.9063 372.4688,18.75 C372.3125,18.4844 372.0313,18.3438 371.7344,18.3438 C371.4375,18.3438 371.2344,18.4375 371.0156,18.75 L370.8438,18.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="123" x="382.5" y="27.8467">SkImageDecoder</text><line style="stroke:#181818;stroke-width:0.5;" x1="354.5" x2="507.5" y1="39" y2="39"/><line style="stroke:#181818;stroke-width:0.5;" x1="354.5" x2="507.5" y1="47" y2="47"/></g><!--class SkJPEGImageDecoder--><g id="elem_SkJPEGImageDecoder"><rect fill="#F1F1F1" height="48" id="SkJPEGImageDecoder" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="188" x="7" y="115"/><ellipse cx="22" cy="131" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M24.3438,126.6719 C23.4063,126.2344 22.8125,126.0938 21.9375,126.0938 C19.3125,126.0938 17.3125,128.1719 17.3125,130.8906 L17.3125,132.0156 C17.3125,134.5938 19.4219,136.4844 22.3125,136.4844 C23.5313,136.4844 24.6875,136.1875 25.4375,135.6406 C26.0156,135.2344 26.3438,134.7813 26.3438,134.3906 C26.3438,133.9375 25.9531,133.5469 25.4844,133.5469 C25.2656,133.5469 25.0625,133.625 24.875,133.8125 C24.4219,134.2969 24.4219,134.2969 24.2344,134.3906 C23.8125,134.6563 23.125,134.7813 22.3594,134.7813 C20.3125,134.7813 19.0156,133.6875 19.0156,131.9844 L19.0156,130.8906 C19.0156,129.1094 20.2656,127.7969 22,127.7969 C22.5781,127.7969 23.1875,127.9531 23.6563,128.2031 C24.1406,128.4844 24.3125,128.7031 24.4063,129.1094 C24.4688,129.5156 24.5,129.6406 24.6406,129.7656 C24.7813,129.9063 25.0156,130.0156 25.2344,130.0156 C25.5,130.0156 25.7656,129.875 25.9375,129.6563 C26.0469,129.5 26.0781,129.3125 26.0781,128.8906 L26.0781,127.4688 C26.0781,127.0313 26.0625,126.9063 25.9688,126.75 C25.8125,126.4844 25.5313,126.3438 25.2344,126.3438 C24.9375,126.3438 24.7344,126.4375 24.5156,126.75 L24.3438,126.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="156" x="36" y="135.8467">SkJPEGImageDecoder</text><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="194" y1="147" y2="147"/><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="194" y1="155" y2="155"/></g><!--class SkPNGImageDecoder--><g id="elem_SkPNGImageDecoder"><rect fill="#F1F1F1" height="48" id="SkPNGImageDecoder" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="185" x="230.5" y="115"/><ellipse cx="245.5" cy="131" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M247.8438,126.6719 C246.9063,126.2344 246.3125,126.0938 245.4375,126.0938 C242.8125,126.0938 240.8125,128.1719 240.8125,130.8906 L240.8125,132.0156 C240.8125,134.5938 242.9219,136.4844 245.8125,136.4844 C247.0313,136.4844 248.1875,136.1875 248.9375,135.6406 C249.5156,135.2344 249.8438,134.7813 249.8438,134.3906 C249.8438,133.9375 249.4531,133.5469 248.9844,133.5469 C248.7656,133.5469 248.5625,133.625 248.375,133.8125 C247.9219,134.2969 247.9219,134.2969 247.7344,134.3906 C247.3125,134.6563 246.625,134.7813 245.8594,134.7813 C243.8125,134.7813 242.5156,133.6875 242.5156,131.9844 L242.5156,130.8906 C242.5156,129.1094 243.7656,127.7969 245.5,127.7969 C246.0781,127.7969 246.6875,127.9531 247.1563,128.2031 C247.6406,128.4844 247.8125,128.7031 247.9063,129.1094 C247.9688,129.5156 248,129.6406 248.1406,129.7656 C248.2813,129.9063 248.5156,130.0156 248.7344,130.0156 C249,130.0156 249.2656,129.875 249.4375,129.6563 C249.5469,129.5 249.5781,129.3125 249.5781,128.8906 L249.5781,127.4688 C249.5781,127.0313 249.5625,126.9063 249.4688,126.75 C249.3125,126.4844 249.0313,126.3438 248.7344,126.3438 C248.4375,126.3438 248.2344,126.4375 248.0156,126.75 L247.8438,126.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="153" x="259.5" y="135.8467">SkPNGImageDecoder</text><line style="stroke:#181818;stroke-width:0.5;" x1="231.5" x2="414.5" y1="147" y2="147"/><line style="stroke:#181818;stroke-width:0.5;" x1="231.5" x2="414.5" y1="155" y2="155"/></g><!--class SkGIFImageDecoder--><g id="elem_SkGIFImageDecoder"><rect fill="#F1F1F1" height="48" id="SkGIFImageDecoder" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="178" x="451" y="115"/><ellipse cx="466" cy="131" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M468.3438,126.6719 C467.4063,126.2344 466.8125,126.0938 465.9375,126.0938 C463.3125,126.0938 461.3125,128.1719 461.3125,130.8906 L461.3125,132.0156 C461.3125,134.5938 463.4219,136.4844 466.3125,136.4844 C467.5313,136.4844 468.6875,136.1875 469.4375,135.6406 C470.0156,135.2344 470.3438,134.7813 470.3438,134.3906 C470.3438,133.9375 469.9531,133.5469 469.4844,133.5469 C469.2656,133.5469 469.0625,133.625 468.875,133.8125 C468.4219,134.2969 468.4219,134.2969 468.2344,134.3906 C467.8125,134.6563 467.125,134.7813 466.3594,134.7813 C464.3125,134.7813 463.0156,133.6875 463.0156,131.9844 L463.0156,130.8906 C463.0156,129.1094 464.2656,127.7969 466,127.7969 C466.5781,127.7969 467.1875,127.9531 467.6563,128.2031 C468.1406,128.4844 468.3125,128.7031 468.4063,129.1094 C468.4688,129.5156 468.5,129.6406 468.6406,129.7656 C468.7813,129.9063 469.0156,130.0156 469.2344,130.0156 C469.5,130.0156 469.7656,129.875 469.9375,129.6563 C470.0469,129.5 470.0781,129.3125 470.0781,128.8906 L470.0781,127.4688 C470.0781,127.0313 470.0625,126.9063 469.9688,126.75 C469.8125,126.4844 469.5313,126.3438 469.2344,126.3438 C468.9375,126.3438 468.7344,126.4375 468.5156,126.75 L468.3438,126.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="146" x="480" y="135.8467">SkGIFImageDecoder</text><line style="stroke:#181818;stroke-width:0.5;" x1="452" x2="628" y1="147" y2="147"/><line style="stroke:#181818;stroke-width:0.5;" x1="452" x2="628" y1="155" y2="155"/></g><!--class SkBMPImageDecoder--><g id="elem_SkBMPImageDecoder"><rect fill="#F1F1F1" height="48" id="SkBMPImageDecoder" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="186" x="664" y="115"/><ellipse cx="679" cy="131" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M681.3438,126.6719 C680.4063,126.2344 679.8125,126.0938 678.9375,126.0938 C676.3125,126.0938 674.3125,128.1719 674.3125,130.8906 L674.3125,132.0156 C674.3125,134.5938 676.4219,136.4844 679.3125,136.4844 C680.5313,136.4844 681.6875,136.1875 682.4375,135.6406 C683.0156,135.2344 683.3438,134.7813 683.3438,134.3906 C683.3438,133.9375 682.9531,133.5469 682.4844,133.5469 C682.2656,133.5469 682.0625,133.625 681.875,133.8125 C681.4219,134.2969 681.4219,134.2969 681.2344,134.3906 C680.8125,134.6563 680.125,134.7813 679.3594,134.7813 C677.3125,134.7813 676.0156,133.6875 676.0156,131.9844 L676.0156,130.8906 C676.0156,129.1094 677.2656,127.7969 679,127.7969 C679.5781,127.7969 680.1875,127.9531 680.6563,128.2031 C681.1406,128.4844 681.3125,128.7031 681.4063,129.1094 C681.4688,129.5156 681.5,129.6406 681.6406,129.7656 C681.7813,129.9063 682.0156,130.0156 682.2344,130.0156 C682.5,130.0156 682.7656,129.875 682.9375,129.6563 C683.0469,129.5 683.0781,129.3125 683.0781,128.8906 L683.0781,127.4688 C683.0781,127.0313 683.0625,126.9063 682.9688,126.75 C682.8125,126.4844 682.5313,126.3438 682.2344,126.3438 C681.9375,126.3438 681.7344,126.4375 681.5156,126.75 L681.3438,126.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="154" x="693" y="135.8467">SkBMPImageDecoder</text><line style="stroke:#181818;stroke-width:0.5;" x1="665" x2="849" y1="147" y2="147"/><line style="stroke:#181818;stroke-width:0.5;" x1="665" x2="849" y1="155" y2="155"/></g><!--class SkPixelRef--><g id="elem_SkPixelRef"><rect fill="#F1F1F1" height="48" id="SkPixelRef" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="109" x="885.5" y="115"/><ellipse cx="900.5" cy="131" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M902.8438,126.6719 C901.9063,126.2344 901.3125,126.0938 900.4375,126.0938 C897.8125,126.0938 895.8125,128.1719 895.8125,130.8906 L895.8125,132.0156 C895.8125,134.5938 897.9219,136.4844 900.8125,136.4844 C902.0313,136.4844 903.1875,136.1875 903.9375,135.6406 C904.5156,135.2344 904.8438,134.7813 904.8438,134.3906 C904.8438,133.9375 904.4531,133.5469 903.9844,133.5469 C903.7656,133.5469 903.5625,133.625 903.375,133.8125 C902.9219,134.2969 902.9219,134.2969 902.7344,134.3906 C902.3125,134.6563 901.625,134.7813 900.8594,134.7813 C898.8125,134.7813 897.5156,133.6875 897.5156,131.9844 L897.5156,130.8906 C897.5156,129.1094 898.7656,127.7969 900.5,127.7969 C901.0781,127.7969 901.6875,127.9531 902.1563,128.2031 C902.6406,128.4844 902.8125,128.7031 902.9063,129.1094 C902.9688,129.5156 903,129.6406 903.1406,129.7656 C903.2813,129.9063 903.5156,130.0156 903.7344,130.0156 C904,130.0156 904.2656,129.875 904.4375,129.6563 C904.5469,129.5 904.5781,129.3125 904.5781,128.8906 L904.5781,127.4688 C904.5781,127.0313 904.5625,126.9063 904.4688,126.75 C904.3125,126.4844 904.0313,126.3438 903.7344,126.3438 C903.4375,126.3438 903.2344,126.4375 903.0156,126.75 L902.8438,126.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="77" x="914.5" y="135.8467">SkPixelRef</text><line style="stroke:#181818;stroke-width:0.5;" x1="886.5" x2="993.5" y1="147" y2="147"/><line style="stroke:#181818;stroke-width:0.5;" x1="886.5" x2="993.5" y1="155" y2="155"/></g><!--class SkImageRef--><g id="elem_SkImageRef"><rect fill="#F1F1F1" height="48" id="SkImageRef" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="119" x="779.5" y="223"/><ellipse cx="794.5" cy="239" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M796.8438,234.6719 C795.9063,234.2344 795.3125,234.0938 794.4375,234.0938 C791.8125,234.0938 789.8125,236.1719 789.8125,238.8906 L789.8125,240.0156 C789.8125,242.5938 791.9219,244.4844 794.8125,244.4844 C796.0313,244.4844 797.1875,244.1875 797.9375,243.6406 C798.5156,243.2344 798.8438,242.7813 798.8438,242.3906 C798.8438,241.9375 798.4531,241.5469 797.9844,241.5469 C797.7656,241.5469 797.5625,241.625 797.375,241.8125 C796.9219,242.2969 796.9219,242.2969 796.7344,242.3906 C796.3125,242.6563 795.625,242.7813 794.8594,242.7813 C792.8125,242.7813 791.5156,241.6875 791.5156,239.9844 L791.5156,238.8906 C791.5156,237.1094 792.7656,235.7969 794.5,235.7969 C795.0781,235.7969 795.6875,235.9531 796.1563,236.2031 C796.6406,236.4844 796.8125,236.7031 796.9063,237.1094 C796.9688,237.5156 797,237.6406 797.1406,237.7656 C797.2813,237.9063 797.5156,238.0156 797.7344,238.0156 C798,238.0156 798.2656,237.875 798.4375,237.6563 C798.5469,237.5 798.5781,237.3125 798.5781,236.8906 L798.5781,235.4688 C798.5781,235.0313 798.5625,234.9063 798.4688,234.75 C798.3125,234.4844 798.0313,234.3438 797.7344,234.3438 C797.4375,234.3438 797.2344,234.4375 797.0156,234.75 L796.8438,234.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="87" x="808.5" y="243.8467">SkImageRef</text><line style="stroke:#181818;stroke-width:0.5;" x1="780.5" x2="897.5" y1="255" y2="255"/><line style="stroke:#181818;stroke-width:0.5;" x1="780.5" x2="897.5" y1="263" y2="263"/></g><!--class SkImageRef_ashmem--><g id="elem_SkImageRef_ashmem"><rect codeLine="8" fill="#F1F1F1" height="64.2969" id="SkImageRef_ashmem" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="187" x="738.5" y="331"/><ellipse cx="753.5" cy="347" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M755.8438,342.6719 C754.9063,342.2344 754.3125,342.0938 753.4375,342.0938 C750.8125,342.0938 748.8125,344.1719 748.8125,346.8906 L748.8125,348.0156 C748.8125,350.5938 750.9219,352.4844 753.8125,352.4844 C755.0313,352.4844 756.1875,352.1875 756.9375,351.6406 C757.5156,351.2344 757.8438,350.7813 757.8438,350.3906 C757.8438,349.9375 757.4531,349.5469 756.9844,349.5469 C756.7656,349.5469 756.5625,349.625 756.375,349.8125 C755.9219,350.2969 755.9219,350.2969 755.7344,350.3906 C755.3125,350.6563 754.625,350.7813 753.8594,350.7813 C751.8125,350.7813 750.5156,349.6875 750.5156,347.9844 L750.5156,346.8906 C750.5156,345.1094 751.7656,343.7969 753.5,343.7969 C754.0781,343.7969 754.6875,343.9531 755.1563,344.2031 C755.6406,344.4844 755.8125,344.7031 755.9063,345.1094 C755.9688,345.5156 756,345.6406 756.1406,345.7656 C756.2813,345.9063 756.5156,346.0156 756.7344,346.0156 C757,346.0156 757.2656,345.875 757.4375,345.6563 C757.5469,345.5 757.5781,345.3125 757.5781,344.8906 L757.5781,343.4688 C757.5781,343.0313 757.5625,342.9063 757.4688,342.75 C757.3125,342.4844 757.0313,342.3438 756.7344,342.3438 C756.4375,342.3438 756.2344,342.4375 756.0156,342.75 L755.8438,342.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="155" x="767.5" y="351.8467">SkImageRef_ashmem</text><line style="stroke:#181818;stroke-width:0.5;" x1="739.5" x2="924.5" y1="363" y2="363"/><line style="stroke:#181818;stroke-width:0.5;" x1="739.5" x2="924.5" y1="371" y2="371"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="119" x="744.5" y="387.9951">bool onDecode()</text></g><!--class AshmemAllocator--><g id="elem_AshmemAllocator"><rect codeLine="12" fill="#F1F1F1" height="64.2969" id="AshmemAllocator" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="386" x="639" y="455"/><ellipse cx="763.75" cy="471" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M766.0938,466.6719 C765.1563,466.2344 764.5625,466.0938 763.6875,466.0938 C761.0625,466.0938 759.0625,468.1719 759.0625,470.8906 L759.0625,472.0156 C759.0625,474.5938 761.1719,476.4844 764.0625,476.4844 C765.2813,476.4844 766.4375,476.1875 767.1875,475.6406 C767.7656,475.2344 768.0938,474.7813 768.0938,474.3906 C768.0938,473.9375 767.7031,473.5469 767.2344,473.5469 C767.0156,473.5469 766.8125,473.625 766.625,473.8125 C766.1719,474.2969 766.1719,474.2969 765.9844,474.3906 C765.5625,474.6563 764.875,474.7813 764.1094,474.7813 C762.0625,474.7813 760.7656,473.6875 760.7656,471.9844 L760.7656,470.8906 C760.7656,469.1094 762.0156,467.7969 763.75,467.7969 C764.3281,467.7969 764.9375,467.9531 765.4063,468.2031 C765.8906,468.4844 766.0625,468.7031 766.1563,469.1094 C766.2188,469.5156 766.25,469.6406 766.3906,469.7656 C766.5313,469.9063 766.7656,470.0156 766.9844,470.0156 C767.25,470.0156 767.5156,469.875 767.6875,469.6563 C767.7969,469.5 767.8281,469.3125 767.8281,468.8906 L767.8281,467.4688 C767.8281,467.0313 767.8125,466.9063 767.7188,466.75 C767.5625,466.4844 767.2813,466.3438 766.9844,466.3438 C766.6875,466.3438 766.4844,466.4375 766.2656,466.75 L766.0938,466.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="128" x="784.25" y="475.8467">AshmemAllocator</text><line style="stroke:#181818;stroke-width:0.5;" x1="640" x2="1024" y1="487" y2="487"/><line style="stroke:#181818;stroke-width:0.5;" x1="640" x2="1024" y1="495" y2="495"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="374" x="645" y="511.9951">bool allocPixelRef(SkBitmap* bm, SkColorTable* ct)</text></g><!--class SkBitmap--><g id="elem_SkBitmap"><rect fill="#F1F1F1" height="48" id="SkBitmap" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="103" x="888.5" y="7"/><ellipse cx="903.5" cy="23" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M905.8438,18.6719 C904.9063,18.2344 904.3125,18.0938 903.4375,18.0938 C900.8125,18.0938 898.8125,20.1719 898.8125,22.8906 L898.8125,24.0156 C898.8125,26.5938 900.9219,28.4844 903.8125,28.4844 C905.0313,28.4844 906.1875,28.1875 906.9375,27.6406 C907.5156,27.2344 907.8438,26.7813 907.8438,26.3906 C907.8438,25.9375 907.4531,25.5469 906.9844,25.5469 C906.7656,25.5469 906.5625,25.625 906.375,25.8125 C905.9219,26.2969 905.9219,26.2969 905.7344,26.3906 C905.3125,26.6563 904.625,26.7813 903.8594,26.7813 C901.8125,26.7813 900.5156,25.6875 900.5156,23.9844 L900.5156,22.8906 C900.5156,21.1094 901.7656,19.7969 903.5,19.7969 C904.0781,19.7969 904.6875,19.9531 905.1563,20.2031 C905.6406,20.4844 905.8125,20.7031 905.9063,21.1094 C905.9688,21.5156 906,21.6406 906.1406,21.7656 C906.2813,21.9063 906.5156,22.0156 906.7344,22.0156 C907,22.0156 907.2656,21.875 907.4375,21.6563 C907.5469,21.5 907.5781,21.3125 907.5781,20.8906 L907.5781,19.4688 C907.5781,19.0313 907.5625,18.9063 907.4688,18.75 C907.3125,18.4844 907.0313,18.3438 906.7344,18.3438 C906.4375,18.3438 906.2344,18.4375 906.0156,18.75 L905.8438,18.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="71" x="917.5" y="27.8467">SkBitmap</text><line style="stroke:#181818;stroke-width:0.5;" x1="889.5" x2="990.5" y1="39" y2="39"/><line style="stroke:#181818;stroke-width:0.5;" x1="889.5" x2="990.5" y1="47" y2="47"/></g><!--class SkMallocPixelRef--><g id="elem_SkMallocPixelRef"><rect fill="#F1F1F1" height="48" id="SkMallocPixelRef" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="154" x="949" y="223"/><ellipse cx="964" cy="239" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M966.3438,234.6719 C965.4063,234.2344 964.8125,234.0938 963.9375,234.0938 C961.3125,234.0938 959.3125,236.1719 959.3125,238.8906 L959.3125,240.0156 C959.3125,242.5938 961.4219,244.4844 964.3125,244.4844 C965.5313,244.4844 966.6875,244.1875 967.4375,243.6406 C968.0156,243.2344 968.3438,242.7813 968.3438,242.3906 C968.3438,241.9375 967.9531,241.5469 967.4844,241.5469 C967.2656,241.5469 967.0625,241.625 966.875,241.8125 C966.4219,242.2969 966.4219,242.2969 966.2344,242.3906 C965.8125,242.6563 965.125,242.7813 964.3594,242.7813 C962.3125,242.7813 961.0156,241.6875 961.0156,239.9844 L961.0156,238.8906 C961.0156,237.1094 962.2656,235.7969 964,235.7969 C964.5781,235.7969 965.1875,235.9531 965.6563,236.2031 C966.1406,236.4844 966.3125,236.7031 966.4063,237.1094 C966.4688,237.5156 966.5,237.6406 966.6406,237.7656 C966.7813,237.9063 967.0156,238.0156 967.2344,238.0156 C967.5,238.0156 967.7656,237.875 967.9375,237.6563 C968.0469,237.5 968.0781,237.3125 968.0781,236.8906 L968.0781,235.4688 C968.0781,235.0313 968.0625,234.9063 967.9688,234.75 C967.8125,234.4844 967.5313,234.3438 967.2344,234.3438 C966.9375,234.3438 966.7344,234.4375 966.5156,234.75 L966.3438,234.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="122" x="978" y="243.8467">SkMallocPixelRef</text><line style="stroke:#181818;stroke-width:0.5;" x1="950" x2="1102" y1="255" y2="255"/><line style="stroke:#181818;stroke-width:0.5;" x1="950" x2="1102" y1="263" y2="263"/></g><!--class AndroidPixelRef--><g id="elem_AndroidPixelRef"><rect fill="#F1F1F1" height="48" id="AndroidPixelRef" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="147" x="960.5" y="339"/><ellipse cx="975.5" cy="355" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M977.8438,350.6719 C976.9063,350.2344 976.3125,350.0938 975.4375,350.0938 C972.8125,350.0938 970.8125,352.1719 970.8125,354.8906 L970.8125,356.0156 C970.8125,358.5938 972.9219,360.4844 975.8125,360.4844 C977.0313,360.4844 978.1875,360.1875 978.9375,359.6406 C979.5156,359.2344 979.8438,358.7813 979.8438,358.3906 C979.8438,357.9375 979.4531,357.5469 978.9844,357.5469 C978.7656,357.5469 978.5625,357.625 978.375,357.8125 C977.9219,358.2969 977.9219,358.2969 977.7344,358.3906 C977.3125,358.6563 976.625,358.7813 975.8594,358.7813 C973.8125,358.7813 972.5156,357.6875 972.5156,355.9844 L972.5156,354.8906 C972.5156,353.1094 973.7656,351.7969 975.5,351.7969 C976.0781,351.7969 976.6875,351.9531 977.1563,352.2031 C977.6406,352.4844 977.8125,352.7031 977.9063,353.1094 C977.9688,353.5156 978,353.6406 978.1406,353.7656 C978.2813,353.9063 978.5156,354.0156 978.7344,354.0156 C979,354.0156 979.2656,353.875 979.4375,353.6563 C979.5469,353.5 979.5781,353.3125 979.5781,352.8906 L979.5781,351.4688 C979.5781,351.0313 979.5625,350.9063 979.4688,350.75 C979.3125,350.4844 979.0313,350.3438 978.7344,350.3438 C978.4375,350.3438 978.2344,350.4375 978.0156,350.75 L977.8438,350.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="115" x="989.5" y="359.8467">AndroidPixelRef</text><line style="stroke:#181818;stroke-width:0.5;" x1="961.5" x2="1106.5" y1="371" y2="371"/><line style="stroke:#181818;stroke-width:0.5;" x1="961.5" x2="1106.5" y1="379" y2="379"/></g><!--reverse link SkImageDecoder to SkJPEGImageDecoder--><g id="link_SkImageDecoder_SkJPEGImageDecoder"><path codeLine="1" d="M342.2575,60.505 C287.0005,78.255 228.043,97.192 172.75,114.953 " fill="none" id="SkImageDecoder-backto-SkJPEGImageDecoder" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="359.395,55,340.4225,54.7925,344.0925,66.2175,359.395,55" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link SkImageDecoder to SkPNGImageDecoder--><g id="link_SkImageDecoder_SkPNGImageDecoder"><path codeLine="2" d="M394.7194,67.6081 C376.7274,85.2661 364.834,96.941 346.762,114.678 " fill="none" id="SkImageDecoder-backto-SkPNGImageDecoder" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="407.566,55,390.5167,63.3259,398.9221,71.8903,407.566,55" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link SkImageDecoder to SkGIFImageDecoder--><g id="link_SkImageDecoder_SkGIFImageDecoder"><path codeLine="3" d="M467.5553,67.549 C485.7133,85.207 497.779,96.941 516.018,114.678 " fill="none" id="SkImageDecoder-backto-SkGIFImageDecoder" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="454.651,55,463.3723,71.8505,471.7384,63.2476,454.651,55" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link SkImageDecoder to SkBMPImageDecoder--><g id="link_SkImageDecoder_SkBMPImageDecoder"><path codeLine="4" d="M518.8548,60.5661 C573.4428,78.3161 631.497,97.192 686.12,114.953 " fill="none" id="SkImageDecoder-backto-SkBMPImageDecoder" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="501.737,55,516.9994,66.272,520.7102,54.8601,501.737,55" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link SkPixelRef to SkImageRef--><g id="link_SkPixelRef_SkImageRef"><path codeLine="6" d="M905.6678,176.0312 C888.8418,193.6892 878.122,204.941 861.222,222.678 " fill="none" id="SkPixelRef-backto-SkImageRef" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="918.085,163,901.324,171.8921,910.0115,180.1703,918.085,163" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link SkImageRef to SkImageRef_ashmem--><g id="link_SkImageRef_SkImageRef_ashmem"><path codeLine="7" d="M836.4805,289.0362 C835.4265,306.2122 835.077,311.884 833.919,330.755 " fill="none" id="SkImageRef-backto-SkImageRef_ashmem" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="837.583,271.07,830.4918,288.6687,842.4692,289.4037,837.583,271.07" style="stroke:#181818;stroke-width:1.0;"/></g><!--link SkImageRef_ashmem to AshmemAllocator--><g id="link_SkImageRef_ashmem_AshmemAllocator"><path codeLine="11" d="M832,395.101 C832,413.457 832,430.6101 832,448.9554 " fill="none" id="SkImageRef_ashmem-to-AshmemAllocator" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="832,454.9554,836,445.9554,832,449.9554,828,445.9554,832,454.9554" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link SkBitmap to SkPixelRef--><g id="link_SkBitmap_SkPixelRef"><path codeLine="15" d="M940,67 C940,84.658 940,96.941 940,114.678 " fill="none" id="SkBitmap-backto-SkPixelRef" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="940,55,936,61,940,67,944,61,940,55" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link SkPixelRef to SkMallocPixelRef--><g id="link_SkPixelRef_SkMallocPixelRef"><path codeLine="17" d="M970.0016,176.9782 C984.3276,194.6362 992.688,204.941 1007.08,222.678 " fill="none" id="SkPixelRef-backto-SkMallocPixelRef" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="958.661,163,965.3422,180.7584,974.661,173.198,958.661,163" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link SkMallocPixelRef to AndroidPixelRef--><g id="link_SkMallocPixelRef_AndroidPixelRef"><path codeLine="18" d="M1028.8819,289.0257 C1030.2719,308.8037 1031,319.196 1032.38,338.965 " fill="none" id="SkMallocPixelRef-backto-AndroidPixelRef" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="1027.62,271.07,1022.8967,289.4464,1034.8672,288.6051,1027.62,271.07" style="stroke:#181818;stroke-width:1.0;"/></g><!--SRC=[ZP1B3e8m443tFSKibSWDZ0d-22QOHjoRKgeIMiOK5YRgtQqK8hy5NKtVlCwdKHOeTXDRmJ4H6fPlruKeEz2Tt-Oa6jNeSOhb1_i9rZga7SjeD7qAUHBNHgdovax-OJzrOSLT2KMuP4KnvF0YO4wCA05psses9nyoD5rt1LuLUb8YPoNgkcgFjcko7sp6dfcbqbAnXmEnMfXXDYXHdraiXGEyj6sj0Oxzp_hbsF9XfpRf0wjvUQ8nJHhu1G00]--></g></svg>

<h2 id="Bitmap内存回收机制"><a href="#Bitmap内存回收机制" class="headerlink" title="Bitmap内存回收机制"></a>Bitmap内存回收机制</h2><p>从Android 8.0开始，Bitmap的pixels数据放在native heap中，通过<code>NativeAllocationRegistry</code>来回收内存。这一节分析<code>NativeAllocationRegistry</code>的原理。</p>
<h3 id="NativeAllocationRegistry内存回收原理"><a href="#NativeAllocationRegistry内存回收原理" class="headerlink" title="NativeAllocationRegistry内存回收原理"></a>NativeAllocationRegistry内存回收原理</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//android-12.1.0_r27\frameworks\base\graphics\java\android\graphics\Bitmap.java</span></span><br><span class="line">    Bitmap(<span class="type">long</span> nativeBitmap, <span class="type">int</span> width, <span class="type">int</span> height, <span class="type">int</span> density,</span><br><span class="line">            <span class="type">boolean</span> requestPremultiplied, <span class="type">byte</span>[] ninePatchChunk,</span><br><span class="line">            NinePatch.InsetStruct ninePatchInsets, <span class="type">boolean</span> fromMalloc) &#123;</span><br><span class="line">        ...... <span class="comment">//代码省略</span></span><br><span class="line">        mNativePtr = nativeBitmap;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">final</span> <span class="type">int</span> <span class="variable">allocationByteCount</span> <span class="operator">=</span> getAllocationByteCount();</span><br><span class="line">        NativeAllocationRegistry registry;</span><br><span class="line">        <span class="keyword">if</span> (fromMalloc) &#123; <span class="comment">//内存在native堆中进行分配</span></span><br><span class="line">            registry = NativeAllocationRegistry.createMalloced(</span><br><span class="line">                    Bitmap.class.getClassLoader(), nativeGetNativeFinalizer(), allocationByteCount);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123; <span class="comment">//fromMalloc=false是内存在Ashmem，或者gpu上进行分配的场景</span></span><br><span class="line">            registry = NativeAllocationRegistry.createNonmalloced(</span><br><span class="line">                    Bitmap.class.getClassLoader(), nativeGetNativeFinalizer(), allocationByteCount);</span><br><span class="line">        &#125;</span><br><span class="line">        registry.registerNativeAllocation(<span class="built_in">this</span>, nativeBitmap);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">native</span> <span class="type">long</span> <span class="title function_">nativeGetNativeFinalizer</span><span class="params">()</span>;</span><br></pre></td></tr></table></figure>

<p>NativeAllocationRegistry的使用比较简单，通过createMalloced/createNonmalloced来构造实例，然后调用registerNativeAllocation来进行注册。构造函数一共有3个参数，第一个是ClassLoader，第二个是nativeGetNativeFinalizer，第三个是内存大小。ClassLoader和内存大小很好理解，<code>nativeGetNativeFinalizer</code>是对应什么呢？它是一个jni函数，实现如下：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//android\android-12.1.0_r27\frameworks\base\libs\hwui\jni\Bitmap.cpp</span></span><br><span class="line"><span class="type">static</span> <span class="type">const</span> JNINativeMethod gBitmapMethods[] = &#123;</span><br><span class="line">    ......</span><br><span class="line">    &#123;   <span class="string">&quot;nativeGetNativeFinalizer&quot;</span>, <span class="string">&quot;()J&quot;</span>, (<span class="type">void</span>*)Bitmap_getNativeFinalizer &#125;,</span><br><span class="line">    ......</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">static</span> <span class="type">void</span> <span class="built_in">Bitmap_destruct</span>(BitmapWrapper* bitmap) &#123;</span><br><span class="line">    <span class="keyword">delete</span> bitmap;  <span class="comment">//最终会调用到析构函数Bitmap::~Bitmap()</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">static</span> jlong <span class="title">Bitmap_getNativeFinalizer</span><span class="params">(JNIEnv*, jobject)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">static_cast</span>&lt;jlong&gt;(<span class="built_in">reinterpret_cast</span>&lt;<span class="type">uintptr_t</span>&gt;(&amp;Bitmap_destruct));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><code>nativeGetNativeFinalizer</code>就是native函数<code>Bitmap_destruct</code>的函数指针，<code>Bitmap_destruct</code>中会调用到native层Bitmap类的析构函数，从而释放内存。</p>
<p>继续看下<code>NativeAllocationRegistry</code>的构造：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> NativeAllocationRegistry <span class="title function_">createNonmalloced</span><span class="params">(</span></span><br><span class="line"><span class="params">        <span class="meta">@NonNull</span> ClassLoader classLoader, <span class="type">long</span> freeFunction, <span class="type">long</span> size)</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">NativeAllocationRegistry</span>(classLoader, freeFunction, size, <span class="literal">false</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> NativeAllocationRegistry <span class="title function_">createMalloced</span><span class="params">(</span></span><br><span class="line"><span class="params">        <span class="meta">@NonNull</span> ClassLoader classLoader, <span class="type">long</span> freeFunction, <span class="type">long</span> size)</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">NativeAllocationRegistry</span>(classLoader, freeFunction, size, <span class="literal">true</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="title function_">NativeAllocationRegistry</span><span class="params">(ClassLoader classLoader, <span class="type">long</span> freeFunction, <span class="type">long</span> size,</span></span><br><span class="line"><span class="params">        <span class="type">boolean</span> mallocAllocation)</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (size &lt; <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">IllegalArgumentException</span>(<span class="string">&quot;Invalid native allocation size: &quot;</span> + size);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">this</span>.classLoader = classLoader;</span><br><span class="line">    <span class="built_in">this</span>.freeFunction = freeFunction;</span><br><span class="line">    <span class="built_in">this</span>.size = mallocAllocation ? (size | IS_MALLOCED) : (size &amp; ~IS_MALLOCED);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>可以看出构造函数只是给成员变量赋值。真正的工作是在registerNativeAllocation中进行的：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//android-12.1.0_r27\libcore\luni\src\main\java\libcore\util\NativeAllocationRegistry.java</span></span><br><span class="line">    <span class="keyword">public</span> <span class="meta">@NonNull</span> Runnable <span class="title function_">registerNativeAllocation</span><span class="params">(<span class="meta">@NonNull</span> Object referent, <span class="type">long</span> nativePtr)</span> &#123;</span><br><span class="line">        ......</span><br><span class="line">        CleanerThunk thunk;</span><br><span class="line">        CleanerRunner result;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            thunk = <span class="keyword">new</span> <span class="title class_">CleanerThunk</span>();</span><br><span class="line">            <span class="type">Cleaner</span> <span class="variable">cleaner</span> <span class="operator">=</span> Cleaner.create(referent, thunk); <span class="comment">//对应sun.misc.Cleaner</span></span><br><span class="line">            result = <span class="keyword">new</span> <span class="title class_">CleanerRunner</span>(cleaner); <span class="comment">//忽略这一行，因为Bitmap调用registerNativeAllocation没有使用返回值</span></span><br><span class="line">            registerNativeAllocation(<span class="built_in">this</span>.size);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (VirtualMachineError vme <span class="comment">/* probably OutOfMemoryError */</span>) &#123;</span><br><span class="line">            applyFreeFunction(freeFunction, nativePtr);</span><br><span class="line">            <span class="keyword">throw</span> vme;</span><br><span class="line">        &#125; <span class="comment">// Other exceptions are impossible.</span></span><br><span class="line">        <span class="comment">// Enable the cleaner only after we can no longer throw anything, including OOME.</span></span><br><span class="line">        thunk.setNativePtr(nativePtr);</span><br><span class="line">        <span class="comment">// Ensure that cleaner doesn&#x27;t get invoked before we enable it.</span></span><br><span class="line">        Reference.reachabilityFence(referent);</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">class</span> <span class="title class_">CleanerThunk</span> <span class="keyword">implements</span> <span class="title class_">Runnable</span> &#123;</span><br><span class="line">        <span class="keyword">private</span> <span class="type">long</span> nativePtr;</span><br><span class="line">        <span class="keyword">public</span> <span class="title function_">CleanerThunk</span><span class="params">()</span> &#123; <span class="built_in">this</span>.nativePtr = <span class="number">0</span>; &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">            <span class="keyword">if</span> (nativePtr != <span class="number">0</span>) &#123;</span><br><span class="line">                applyFreeFunction(freeFunction, nativePtr); <span class="comment">//回收内存</span></span><br><span class="line">                registerNativeFree(size);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setNativePtr</span><span class="params">(<span class="type">long</span> nativePtr)</span> &#123; <span class="built_in">this</span>.nativePtr = nativePtr; &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//jni函数，执行native内存回收</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">native</span> <span class="keyword">void</span> <span class="title function_">applyFreeFunction</span><span class="params">(<span class="type">long</span> freeFunction, <span class="type">long</span> nativePtr)</span>;</span><br></pre></td></tr></table></figure>

<p>看来NativeAllocationRegistry是通过sun.misc.Cleaner来执行内存回收的。</p>
<h3 id="Cleaner源码分析"><a href="#Cleaner源码分析" class="headerlink" title="Cleaner源码分析"></a>Cleaner源码分析</h3><p>（源码分析基于jdk1.8.0）</p>
<p><strong>首先，</strong> Cleaner是一个虚引用，继承自PhantomReference，如下图：</p>
<?xml version="1.0" encoding="us-ascii" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" height="281px" preserveAspectRatio="none" style="width:233px;height:281px;background:#FFFFFF;" version="1.1" viewBox="0 0 233 281" width="233px" zoomAndPan="magnify"><defs/><g><!--class Reference--><g id="elem_Reference"><rect codeLine="1" fill="#F1F1F1" height="48" id="Reference" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="149" x="40" y="10"/><ellipse cx="55" cy="26" fill="#A9DCDF" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M57.0781,27.8125 L57.4688,28.7969 L57.0781,28.7969 C56.625,28.7969 56.5156,28.8125 56.3594,28.9219 C56.1094,29.0781 55.9531,29.3594 55.9531,29.6563 C55.9531,29.9219 56.0938,30.1719 56.3125,30.3281 C56.4531,30.4531 56.6563,30.5 57.0781,30.5 L59.4375,30.5 C59.7969,30.5 60.0156,30.4688 60.1563,30.375 C60.4063,30.2344 60.5625,29.9375 60.5625,29.6563 C60.5625,29.375 60.4219,29.125 60.2031,28.9688 C60.0313,28.8281 59.875,28.7969 59.4063,28.7969 L56.0156,20.5938 L52.3438,20.5938 C51.8906,20.5938 51.7656,20.6094 51.6094,20.7031 C51.3594,20.875 51.2031,21.1563 51.2031,21.4375 C51.2031,21.7188 51.3438,21.9688 51.5625,22.1406 C51.7344,22.25 51.9063,22.2813 52.3438,22.2813 L53.4219,22.2813 L50.7813,28.7969 C50.3594,28.7969 50.2031,28.8125 50.0469,28.9219 C49.7969,29.0781 49.6406,29.3594 49.6406,29.6563 C49.6406,30.2188 50.0156,30.5 50.7656,30.5 L53.0313,30.5 C53.3906,30.5 53.6094,30.4688 53.7344,30.375 C54,30.2344 54.1406,29.9375 54.1406,29.6563 C54.1406,29.375 54.0156,29.125 53.7969,28.9531 C53.625,28.8281 53.4844,28.7969 53.0313,28.7969 L52.6406,28.7969 L53.0313,27.8125 L57.0781,27.8125 Z M56.375,26.1094 L53.7031,26.1094 L55.0469,22.8438 L56.375,26.1094 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="74" x="69" y="30.8467">Reference</text><rect fill="#FFFFFF" height="15.9688" style="stroke:#181818;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="41" x="151" y="7"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="39" x="152" y="19.1387">Object</text><line style="stroke:#181818;stroke-width:0.5;" x1="41" x2="188" y1="42" y2="42"/><line style="stroke:#181818;stroke-width:0.5;" x1="41" x2="188" y1="50" y2="50"/></g><!--class PhantomReference--><g id="elem_PhantomReference"><rect codeLine="2" fill="#F1F1F1" height="48" id="PhantomReference" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="215" x="7" y="118"/><ellipse cx="22" cy="134" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M24.3438,129.6719 C23.4063,129.2344 22.8125,129.0938 21.9375,129.0938 C19.3125,129.0938 17.3125,131.1719 17.3125,133.8906 L17.3125,135.0156 C17.3125,137.5938 19.4219,139.4844 22.3125,139.4844 C23.5313,139.4844 24.6875,139.1875 25.4375,138.6406 C26.0156,138.2344 26.3438,137.7813 26.3438,137.3906 C26.3438,136.9375 25.9531,136.5469 25.4844,136.5469 C25.2656,136.5469 25.0625,136.625 24.875,136.8125 C24.4219,137.2969 24.4219,137.2969 24.2344,137.3906 C23.8125,137.6563 23.125,137.7813 22.3594,137.7813 C20.3125,137.7813 19.0156,136.6875 19.0156,134.9844 L19.0156,133.8906 C19.0156,132.1094 20.2656,130.7969 22,130.7969 C22.5781,130.7969 23.1875,130.9531 23.6563,131.2031 C24.1406,131.4844 24.3125,131.7031 24.4063,132.1094 C24.4688,132.5156 24.5,132.6406 24.6406,132.7656 C24.7813,132.9063 25.0156,133.0156 25.2344,133.0156 C25.5,133.0156 25.7656,132.875 25.9375,132.6563 C26.0469,132.5 26.0781,132.3125 26.0781,131.8906 L26.0781,130.4688 C26.0781,130.0313 26.0625,129.9063 25.9688,129.75 C25.8125,129.4844 25.5313,129.3438 25.2344,129.3438 C24.9375,129.3438 24.7344,129.4375 24.5156,129.75 L24.3438,129.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="140" x="36" y="138.8467">PhantomReference</text><rect fill="#FFFFFF" height="15.9688" style="stroke:#181818;stroke-width:1.0;stroke-dasharray:2.0,2.0;" width="41" x="184" y="115"/><text fill="#000000" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="39" x="185" y="127.1387">Object</text><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="221" y1="150" y2="150"/><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="221" y1="158" y2="158"/></g><!--class Cleaner--><g id="elem_Cleaner"><rect fill="#F1F1F1" height="48" id="Cleaner" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="87" x="71" y="226"/><ellipse cx="86" cy="242" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M88.3438,237.6719 C87.4063,237.2344 86.8125,237.0938 85.9375,237.0938 C83.3125,237.0938 81.3125,239.1719 81.3125,241.8906 L81.3125,243.0156 C81.3125,245.5938 83.4219,247.4844 86.3125,247.4844 C87.5313,247.4844 88.6875,247.1875 89.4375,246.6406 C90.0156,246.2344 90.3438,245.7813 90.3438,245.3906 C90.3438,244.9375 89.9531,244.5469 89.4844,244.5469 C89.2656,244.5469 89.0625,244.625 88.875,244.8125 C88.4219,245.2969 88.4219,245.2969 88.2344,245.3906 C87.8125,245.6563 87.125,245.7813 86.3594,245.7813 C84.3125,245.7813 83.0156,244.6875 83.0156,242.9844 L83.0156,241.8906 C83.0156,240.1094 84.2656,238.7969 86,238.7969 C86.5781,238.7969 87.1875,238.9531 87.6563,239.2031 C88.1406,239.4844 88.3125,239.7031 88.4063,240.1094 C88.4688,240.5156 88.5,240.6406 88.6406,240.7656 C88.7813,240.9063 89.0156,241.0156 89.2344,241.0156 C89.5,241.0156 89.7656,240.875 89.9375,240.6563 C90.0469,240.5 90.0781,240.3125 90.0781,239.8906 L90.0781,238.4688 C90.0781,238.0313 90.0625,237.9063 89.9688,237.75 C89.8125,237.4844 89.5313,237.3438 89.2344,237.3438 C88.9375,237.3438 88.7344,237.4375 88.5156,237.75 L88.3438,237.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="55" x="100" y="246.8467">Cleaner</text><line style="stroke:#181818;stroke-width:0.5;" x1="72" x2="157" y1="258" y2="258"/><line style="stroke:#181818;stroke-width:0.5;" x1="72" x2="157" y1="266" y2="266"/></g><!--reverse link Reference to PhantomReference--><g id="link_Reference_PhantomReference"><path codeLine="3" d="M114.5,76 C114.5,93.658 114.5,99.941 114.5,117.678 " fill="none" id="Reference-backto-PhantomReference" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="114.5,58,108.5,76,120.5,76,114.5,58" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link PhantomReference to Cleaner--><g id="link_PhantomReference_Cleaner"><path codeLine="4" d="M114.5,184 C114.5,201.6584 114.5,207.9408 114.5,225.6784 " fill="none" id="PhantomReference-backto-Cleaner" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="114.5,166,108.5,184,120.5,184,114.5,166" style="stroke:#181818;stroke-width:1.0;"/></g><!--SRC=[IqmgBYbAJ2vH24fDIorApKjEjV5FoafDBh7ZIiv9B2vM2CX8p2l9pyMKXeiesDJewcAeuq8NW2XppabDp4ij0W00]--></g></svg>

<p><strong>第二：</strong> Cleaner的父类Reference的静态代码块中会启动一个线程ReferenceHandler，这个线程永远不会退出：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">class</span> <span class="title class_">Reference</span>&lt;T&gt; &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">class</span> <span class="title class_">ReferenceHandler</span> <span class="keyword">extends</span> <span class="title class_">Thread</span> &#123;</span><br><span class="line">        ......</span><br><span class="line">        <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">            <span class="keyword">while</span> (<span class="literal">true</span>) &#123; <span class="comment">//while循环永远不会退出</span></span><br><span class="line">                tryHandlePending(<span class="literal">true</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        <span class="type">ThreadGroup</span> <span class="variable">tg</span> <span class="operator">=</span> Thread.currentThread().getThreadGroup();</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">ThreadGroup</span> <span class="variable">tgn</span> <span class="operator">=</span> tg;</span><br><span class="line">             tgn != <span class="literal">null</span>;</span><br><span class="line">             tg = tgn, tgn = tg.getParent());</span><br><span class="line">        <span class="type">Thread</span> <span class="variable">handler</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ReferenceHandler</span>(tg, <span class="string">&quot;Reference Handler&quot;</span>);</span><br><span class="line">        handler.setPriority(Thread.MAX_PRIORITY); <span class="comment">//高优先级</span></span><br><span class="line">        handler.setDaemon(<span class="literal">true</span>);</span><br><span class="line">        handler.start();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// provide access in SharedSecrets</span></span><br><span class="line">        SharedSecrets.setJavaLangRefAccess(<span class="keyword">new</span> <span class="title class_">JavaLangRefAccess</span>() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">tryHandlePendingReference</span><span class="params">()</span> &#123;</span><br><span class="line">                <span class="keyword">return</span> tryHandlePending(<span class="literal">false</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<p><strong>第三：</strong> pending是一个Reference链表，由GC来赋值。pending链表中的Reference都在等待被加入到ReferenceQueue中，如果Reference没有关联到ReferenceQueue，就不会被添加到pending列表。而ReferenceHandler是一个永远不会退出的线程，一直从链表中获取元素，当元素是Cleaner类型时就会执行Cleaner.clean()方法，否则就会加入到ReferenceQueue队列中。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* List of References waiting to be enqueued.  The collector adds</span></span><br><span class="line"><span class="comment"> * References to this list, while the Reference-handler thread removes</span></span><br><span class="line"><span class="comment"> * them.  This list is protected by the above lock object. The</span></span><br><span class="line"><span class="comment"> * list uses the discovered field to link its elements.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> Reference&lt;Object&gt; pending = <span class="literal">null</span>;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">static</span> <span class="type">boolean</span> <span class="title function_">tryHandlePending</span><span class="params">(<span class="type">boolean</span> waitForNotify)</span> &#123;</span><br><span class="line">    Reference&lt;Object&gt; r;</span><br><span class="line">    Cleaner c;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="keyword">synchronized</span> (lock) &#123;</span><br><span class="line">            <span class="keyword">if</span> (pending != <span class="literal">null</span>) &#123;</span><br><span class="line">                r = pending;</span><br><span class="line">                <span class="comment">// &#x27;instanceof&#x27; might throw OutOfMemoryError sometimes</span></span><br><span class="line">                <span class="comment">// so do this before un-linking &#x27;r&#x27; from the &#x27;pending&#x27; chain...</span></span><br><span class="line">                c = r <span class="keyword">instanceof</span> Cleaner ? (Cleaner) r : <span class="literal">null</span>;</span><br><span class="line">                <span class="comment">// unlink &#x27;r&#x27; from &#x27;pending&#x27; chain</span></span><br><span class="line">                pending = r.discovered; <span class="comment">//pending链表指向下一个Reference</span></span><br><span class="line">                r.discovered = <span class="literal">null</span>;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="comment">// The waiting on the lock may cause an OutOfMemoryError</span></span><br><span class="line">                <span class="comment">// because it may try to allocate exception objects.</span></span><br><span class="line">                <span class="keyword">if</span> (waitForNotify) &#123;</span><br><span class="line">                    lock.wait(); <span class="comment">//pending为空，线程阻塞等待。</span></span><br><span class="line">                    <span class="comment">//当GC每次执行收集流程之前都会获取lock，然后将被回收的Reference放到pending链表中，然后唤醒阻塞线程</span></span><br><span class="line">                &#125;</span><br><span class="line">                <span class="comment">// retry if waited</span></span><br><span class="line">                <span class="keyword">return</span> waitForNotify;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">catch</span> (OutOfMemoryError x) &#123;</span><br><span class="line">        <span class="comment">// Give other threads CPU time so they hopefully drop some live references</span></span><br><span class="line">        <span class="comment">// and GC reclaims some space.</span></span><br><span class="line">        <span class="comment">// Also prevent CPU intensive spinning in case &#x27;r instanceof Cleaner&#x27; above</span></span><br><span class="line">        <span class="comment">// persistently throws OOME for some time...</span></span><br><span class="line">        Thread.<span class="keyword">yield</span>();</span><br><span class="line">        <span class="comment">// retry</span></span><br><span class="line">        <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">    &#125; <span class="keyword">catch</span> (InterruptedException x) &#123;</span><br><span class="line">        <span class="comment">// retry</span></span><br><span class="line">        <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Fast path for cleaners</span></span><br><span class="line">    <span class="keyword">if</span> (c != <span class="literal">null</span>) &#123;</span><br><span class="line">        c.clean();  <span class="comment">//执行Cleaner的clean()方法</span></span><br><span class="line">        <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    ReferenceQueue&lt;? <span class="built_in">super</span> Object&gt; q = r.queue;</span><br><span class="line">    <span class="keyword">if</span> (q != ReferenceQueue.NULL) q.enqueue(r);  <span class="comment">//将其他Reference加入到ReferenceQueue中。</span></span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="参考文章"><a href="#参考文章" class="headerlink" title="参考文章"></a>参考文章</h2><p><a target="_blank" rel="noopener external nofollow noreferrer" href="https://developer.android.google.cn/guide/topics/graphics/hardware-accel?hl=zh-cn">硬件加速</a><br><a target="_blank" rel="noopener external nofollow noreferrer" href="https://muyangmin.github.io/glide-docs-cn/doc/hardwarebitmaps.html">硬件位图</a><br><a target="_blank" rel="noopener external nofollow noreferrer" href="https://www.dazhuanlan.com/zipaiwang/topics/992879">Android硬件位图填坑之获取硬件画布</a></p>

    </div>

    
    
    

    <footer class="post-footer">
          <div class="post-tags">
              <a href="/tags/Android/" rel="tag"># Android</a>
              <a href="/tags/Bitmap/" rel="tag"># Bitmap</a>
          </div>

        

          <div class="post-nav">
            <div class="post-nav-item">
                <a href="/posts/f45b8d80.html" rel="prev" title="Java注解原理">
                  <i class="fa fa-angle-left"></i> Java注解原理
                </a>
            </div>
            <div class="post-nav-item">
                <a href="/posts/c09f2087.html" rel="next" title="Android UI 绘制流程">
                  Android UI 绘制流程 <i class="fa fa-angle-right"></i>
                </a>
            </div>
          </div>
    </footer>
  </article>
</div>






</div>
  </main>

  <footer class="footer">
    <div class="footer-inner">

  <div class="copyright">
    &copy; 
    <span itemprop="copyrightYear">2024</span>
    <span class="with-love">
      <i class="fa fa-heart"></i>
    </span>
    <span class="author" itemprop="copyrightHolder">Jason</span>
  </div>
  <div class="powered-by">由 <a href="https://hexo.io/" rel="noopener external nofollow noreferrer" target="_blank">Hexo</a> & <a href="https://theme-next.js.org/pisces/" rel="noopener external nofollow noreferrer" target="_blank">NexT.Pisces</a> 强力驱动
  </div>

    </div>
  </footer>

  
  <div class="back-to-top" role="button" aria-label="返回顶部">
    <i class="fa fa-arrow-up fa-lg"></i>
    <span>0%</span>
  </div>

<noscript>
  <div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>


  
  <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js" integrity="sha256-XL2inqUJaslATFnHdJOi9GfQ60on8Wx1C2H8DYiN1xY=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/next-theme-pjax/0.6.0/pjax.min.js" integrity="sha256-vxLn1tSKWD4dqbMRyv940UYw4sXgMtYcK6reefzZrao=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/fancyapps-ui/5.0.24/fancybox/fancybox.umd.js" integrity="sha256-oyhjPiYRWGXaAt+ny/mTMWOnN1GBoZDUQnzzgC7FRI4=" crossorigin="anonymous"></script>
<script src="/js/comments.js"></script><script src="/js/utils.js"></script><script src="/js/motion.js"></script><script src="/js/next-boot.js"></script><script src="/js/pjax.js"></script>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/hexo-generator-searchdb/1.4.1/search.js" integrity="sha256-1kfA5uHPf65M5cphT2dvymhkuyHPQp5A53EGZOnOLmc=" crossorigin="anonymous"></script>
<script src="/js/third-party/search/local-search.js"></script>


  <script class="next-config" data-name="mermaid" type="application/json">{"enable":true,"theme":{"light":"default","dark":"dark"},"js":{"url":"https://cdnjs.cloudflare.com/ajax/libs/mermaid/10.5.0/mermaid.min.js","integrity":"sha256-K7oJiQlDulzl24ZUFOywuYme1JqBBvQzK6m8qHjt9Gk="}}</script>
  <script type="module" src="/js/zenuml-definition-074a43fa.js"></script>
  <script type="module" src="/js/mermaid-zenuml.esm.min.mjs"></script>
  <script src="/js/third-party/tags/mermaid.js"></script>


  <script src="/js/third-party/fancybox.js"></script>



  




  

  <script class="next-config" data-name="enableMath" type="application/json">true</script><script class="next-config" data-name="mathjax" type="application/json">{"enable":true,"tags":"none","js":{"url":"https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-mml-chtml.js","integrity":"sha256-MASABpB4tYktI2Oitl4t+78w/lyA+D7b/s9GEP0JOGI="}}</script>
<script src="/js/third-party/math/mathjax.js"></script>



</body>
</html>
